﻿using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace RainEngine.Effects
{
    /// <summary>
    /// 对Generic.fx文件的封装。可选择的纹理、雾化和光照。
    /// </summary>
    public class GenericEffect :DiffuseLightEffectWrapper
    {
        EffectParameter specularColorParam;
        EffectParameter specularPowerParam;
        EffectParameter diffuseTextureParam;
        EffectParameter diffuseTextureUVTileParam;
        EffectParameter detailTextureParam;
        EffectParameter detailTextureUVTileParam;
        EffectParameter detailTextureEnabledTileParam;
        
        bool preferPerPixelLighting;
        bool textureEnabled;
        bool normalMappingEnabled;

        #region 属性

        /// <summary>
        /// 获取或设置镜面高光颜色。
        /// </summary>
        public Vector3 SpecularColor
        {
            get { return specularColorParam.GetValueVector3(); }
            set { specularColorParam.SetValue(value); }
        }

        /// <summary>
        /// 获取或设置镜面高光强度。
        /// </summary>
        public float SpecularPower
        {
            get { return specularPowerParam.GetValueSingle(); }
            set { specularPowerParam.SetValue(value); }
        }

        /// <summary>
        /// 获取或设置漫反射纹理。
        /// </summary>
        public Texture2D DiffuseTexture
        {
            get { return diffuseTextureParam.GetValueTexture2D(); }
            set { diffuseTextureParam.SetValue(value); }
        }

        /// <summary>
        /// 获取或设置漫反射纹理的平铺次数。
        /// </summary>
        public Vector2 DiffuseTextureUVTile
        {
            get { return diffuseTextureUVTileParam.GetValueVector2(); }
            set { diffuseTextureUVTileParam.SetValue(value); }
        }
        
        /// <summary>
        /// 获取或设置细节纹理。
        /// </summary>
        public Texture2D DetailTexture
        {
            get { return detailTextureParam.GetValueTexture2D(); }
            set { detailTextureParam.SetValue(value); }
        }

        /// <summary>
        /// 获取或设置纹理的平铺次数。
        /// </summary>
        public Vector2 DetailTextureUVTile
        {
            get { return detailTextureUVTileParam.GetValueVector2(); }
            set
            {
                detailTextureUVTileParam.SetValue(value);
            }
        }

        /// <summary>
        /// 获取或设置是否将细节纹理施加到漫反射纹理上。
        /// </summary>
        public bool DetailTextureEnabled
        {
            get { return detailTextureEnabledTileParam.GetValueBoolean(); }
            set { detailTextureEnabledTileParam.SetValue(value); }
        }
        
        /// <summary>
        /// 获取或设置是否使用纹理。
        /// </summary>
        public bool TextureEnabled
        {
            get { return textureEnabled; }
            set
            {
                if (textureEnabled != value)
                {
                    textureEnabled = value;
                    dirtyFlags |= EffectDirtyFlags.ShaderIndex;
                }
            }
        }
        
        /// <summary>
        /// 获取或设置是否开启逐像素光照
        /// </summary>
        public bool PreferPerPixelLighting
        {
            get { return preferPerPixelLighting; }

            set
            {
                if (preferPerPixelLighting != value)
                {
                    preferPerPixelLighting = value;
                    dirtyFlags |= EffectDirtyFlags.ShaderIndex;
                }
            }
        }

        /// <summary>
        /// 获取或设置是否开启法线映射
        /// </summary>
        public bool NormalMappingEnabled
        {
            get { return normalMappingEnabled; }
            set
            {
                if (normalMappingEnabled != value)
                {
                    normalMappingEnabled = value;
                    // 使用法线映射必须开启光照
                    LightingEnabled = true;
                    dirtyFlags |= EffectDirtyFlags.ShaderIndex;
                }
            }
        }

        #endregion

        /// <summary>
        /// 创建一个新GenericEffect对象。
        /// </summary>
        public GenericEffect():base(RainGE.GenericEffect){}

        /// <summary>
        /// 缓存effect的参数。
        /// </summary>
        protected override void CacheEffectParameters()
        {
            base.CacheEffectParameters();

            specularColorParam = parameters["SpecularColor"];
            specularPowerParam = parameters["SpecularPower"];
            diffuseTextureParam = parameters["DiffuseTexture"];
            diffuseTextureUVTileParam = parameters["DiffuseTextureUVTile"];
            detailTextureParam = parameters["DetailTexture"];
            detailTextureUVTileParam = parameters["DetailTextureUVTile"];
            detailTextureEnabledTileParam = parameters["DetailTextureEnabled"];
        }

        /// <summary>
        /// 在effect.Apply()方法执行之前根据需要重新计算shader参数。
        /// </summary>
        public override void OnApply()
        {
            base.OnApply();
            
            // 重新设置shader index参数
            if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
            {
                int shaderIndex = 0;

                if (fogEnabled)
                    shaderIndex += 1; 

                if (textureEnabled)
                    shaderIndex += 2;

                if (lightingEnabled)
                {
                    if (preferPerPixelLighting)
                        shaderIndex += 8;                    
                    else
                        shaderIndex += 4;
                }

                if (normalMappingEnabled)
                {
                    shaderIndex = 12;
                    if (fogEnabled)
                        shaderIndex += 1; 
                }    

                shaderIndexParam.SetValue(shaderIndex);

                dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
            }
        }
    }
}